﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace InversPong.Model
{
    public class Map
    {
        public IList<Bat> Bats { get; private set; }
        public IList<Bomb> Bombs { get; private set; }
        public IList<PowerUp> PowerUps { get; private set; }

        public IList<MovableObject> Movables { get; private set; }

        public int Width { get; private set; }
        public int Height { get; private set; }

        private Random r = new Random();

        public Vector2 GeneratorOrigin() 
        {  
            return new Vector2(Width / 2, Height / 2);
        }

        public Map(int width, int height)
        {
            if (width >= 0 && height >= 0)
            {
                Width = width;
                Height = height;

                Bats = new List<Bat>();
                Bombs = new List<Bomb>();
                PowerUps = new List<PowerUp>();
                Movables = new List<MovableObject>();
            }
            else
            {
                throw new ArgumentOutOfRangeException("Width or Height of the map can not be lower than 0");
            }
        }

        public void addBat(Bat bat)
        {
            if (bat != null)
            {
                Bats.Add(bat);
            }
            else
            {
                throw new NullReferenceException("Map can not add a null bat");
            }
        }

        public void addBomb(Bomb bomb)
        {
            if (bomb != null)
            {
                Bombs.Add(bomb);
                Movables.Add(bomb);
            }
            else
            {
                throw new NullReferenceException("Map can not add a null bomb");
            }
        }

        public void addPowerUp(PowerUp powerUp)
        {
            if (powerUp != null)
            {
                PowerUps.Add(powerUp);
                Movables.Add(powerUp);
            }
            else 
            {
                throw new NullReferenceException("Map can not add a null powerUp");
            }
        }

        public void removeBat(Bat bat)
        {
            if (bat != null && Bats.Contains(bat))
            {
                Bats.Remove(bat);
            }
        }

        public void removeBomb(Bomb bomb)
        {
            if (bomb != null && Bombs.Contains(bomb) && Movables.Contains(bomb))
            {
                Bombs.Remove(bomb);
                Movables.Remove(bomb);
            }
        }

        public void removePowerUp(PowerUp powerUp)
        {
            if (powerUp != null && PowerUps.Contains(powerUp) && Movables.Contains(powerUp))
            {
                PowerUps.Remove(powerUp);
                Movables.Remove(powerUp);
            }
        }

        public void RemoveMovableObject(MovableObject obj)
        {
            if (obj is Bomb)
            {
                removeBomb((Bomb) obj);
            }
            else if (obj is PowerUp)
            {
                removePowerUp((PowerUp) obj);
            }
        }

        public void removeAll()
        {
            PowerUps.Clear();            
            Bombs.Clear();
            Movables.Clear();
        }

        public void GenerateRandomBomb()
        {
            double angle = (Math.PI * 3 / 4) * r.NextDouble() + (Math.PI * 3 / 4);
            var dir1 = new Vector2(-(float)Math.Cos(angle), -(float)Math.Sin(angle));
            var dir2 = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));

            addBomb(new SimpleBomb(GeneratorOrigin(), dir1));
            addBomb(new SimpleBomb(GeneratorOrigin(), dir2));
        }

        public void GenerateRandomPowerUp()
        {
            double angle = (Math.PI * 2 / 3) * r.NextDouble() + (Math.PI * 2 / 3);
            var dir1 = new Vector2(-(float)Math.Cos(angle), -(float)Math.Sin(angle));
            var dir2 = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));

            Vector2 position = new Vector2(GeneratorOrigin().X - PowerUp.defaultPowerUpSize[0] / 2, GeneratorOrigin().Y - PowerUp.defaultPowerUpSize[1] / 2);
            PowerUp.Types type = PowerUp.GetRandomType();

            addPowerUp(new PowerUp(position, dir1, type, TimeSpan.Zero));
            addPowerUp(new PowerUp(position, dir2, type, TimeSpan.Zero));
        }


    }
}
